/**
 * @param { promise }  promise The Promise function passed in
 * @param {Function} finallyCallback - Finally Execution Function
 * @param {object=} errorExt - Extending the Error Object
 * @return { Promise } Return a Promise
 *
 */
function to<T>(
  promise: Promise<T>,
  finallyCallback?: () => void,
  errorExt?: string | object,
): Promise<[any, T | undefined]> {
  return promise
    .then((data: T) => {
      return [null, data] as [null, T]
    })
    .catch((err) => {
      if (errorExt) {
        const parsedError = Object.assign({}, err, errorExt)
        return [parsedError, undefined] as [typeof parsedError, undefined]
      }

      return [err, undefined] as [typeof err, undefined]
    })
    .finally(() => finallyCallback && finallyCallback())
}

export default to
